﻿using System;
using System.IO;
using System.Configuration;
using System.Text.RegularExpressions;

namespace DuJianliang.ApplicationPlatform.Common
{
    /// <summary>
    /// 提供了以 xml 格式记录日志的方法。每一个日志都被单独保存为 xml 格式的文件。该类中的所有方法都不会引发异常。
    /// </summary>
    /// <remarks>
    /// 如果想关闭记录日志的功能，可以通过配置文件中 AppSettings 配置节的 DuJianliang.ClassLibrary.LoggerTurnOff 来实现。该配置项为正则表达式。
    /// 程序使用 LogType 和配置的正则表达式进行匹配，如能匹配则不记录日志（表示关掉指定LogType记录日志的功能）。
    /// </remarks>
    public static class Logger
    {
        /// <summary>
        /// 在指定的目录下创建以 logType 命名的子目录，并在其中写入日志文件。
        /// </summary>
        /// <param name="path">
        /// 保存日志文件的路径。如果未指定该参数（Null, 空字符串），则使用配置文件中 AppSettings 配置节的 DuJianliang.ClassLibrary.LogPath 配置的内容。
        /// </param>
        /// <param name="logType">日志类型</param>
        /// <param name="creater">日志类型</param>
        /// <param name="message">日志消息</param>
        /// <param name="exception">异常对象</param>
        public static void Write(string path, int logType, string creater, string message, Exception exception)
        {
            try
            {
                LogData logData = new LogData();
                logData.LogType = logType;
                logData.Creater = creater;
                logData.CreationDateTime = DateTime.Now;
                logData.Message = message;

                if (exception != null)
                {
                    logData.KeyValueList.Add(new KeyValueItem("Exception.Message", exception.Message));
                    logData.KeyValueList.Add(new KeyValueItem("Exception.StackTrace", exception.StackTrace));
                    logData.KeyValueList.Add(new KeyValueItem("Exception.Source", exception.Source));
                }

                Logger.Write(path, logData);
            }
            catch
            {
                // do nothing
            }
        }

        /// <summary>
        /// 在指定的目录下创建以 logType 命名的子目录，并在其中写入日志文件。
        /// </summary>
        /// <param name="path">
        /// 保存日志文件的路径。如果未指定该参数（Null, 空字符串），则使用配置文件中 AppSettings 配置节的 DuJianliang.ClassLibrary.LogPath 配置的内容。
        /// </param>
        /// <param name="logType">日志类型</param>
        /// <param name="creater">创建人</param>
        /// <param name="message">日志消息</param>
        public static void Write(string path, int logType, string creater, string message)
        {
            try
            {
                LogData logData = new LogData();
                logData.LogType = logType;
                logData.Creater = creater;
                logData.CreationDateTime = DateTime.Now;
                logData.Message = message;

                Logger.Write(path, logData);
            }
            catch
            {
                // do nothing
            }
        }

        /// <summary>
        /// 在指定的目录下创建以 LogData.LogType 命名的子目录，并在其中写入日志文件。
        /// </summary>
        /// <param name="path">
        /// 保存日志文件的路径。如果未指定该参数（Null, 空字符串），则使用配置文件中 AppSettings 配置节的 DuJianliang.ClassLibrary.LogPath 配置的内容。
        /// </param>
        /// <param name="logData">
        /// 日志数据对象。该对象以xml文件的形式保存。
        /// </param>
        public static void Write(string path, LogData logData)
        {
            if (logData == null)
            {
                return;
            }

            // 如果未指定 path 参数的值，则使用 <add key="DuJianliang.ClassLibrary.LogPath" value=""/> 配置的内容。
            if (string.IsNullOrWhiteSpace(path))
            {
                path = ConfigurationManager.AppSettings["DuJianliang.ClassLibrary.LogPath"];

                if (string.IsNullOrWhiteSpace(path))
                {
                    return;
                }
            }

            // 使用 logData.LogType 和配置的正则表达式进行匹配，如能匹配则不记录日志（表示关掉指定LogType记录日志的功能）。
            string loggerTurnOff = ConfigurationManager.AppSettings["DuJianliang.ClassLibrary.LoggerTurnOff"];
            if (!string.IsNullOrWhiteSpace(loggerTurnOff))
            {
                Regex regex = new Regex(loggerTurnOff, RegexOptions.IgnoreCase);
                if (regex.IsMatch(logData.LogType.ToString()))
                {
                    return;
                }
            }

            try
            {
                DateTime dateTime = DateTime.Now;

                // 使用日志类型作为子目录
                string dirLogType = logData.LogType.ToString();

                // 获取与平台无关的路径分隔符
                string dirSeparatorChar = Path.DirectorySeparatorChar.ToString();

                // 组合日志目录字符串
                string filePath = path + (path.EndsWith(dirSeparatorChar) ? "" : dirSeparatorChar) 
                    + dirLogType + dirSeparatorChar;

                // 检查目录是否存在，不存在则创建
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }

                // 创建文件名，文件名格式：8位日期-9位时间(3位毫秒)-GUID前8位-日志类型.xml
                string fileName = string.Format("{0}-{1}-{2}.xml"
                    , dateTime.ToString("yyyyMMdd-HHmmssfff")
                    , Guid.NewGuid().ToString().Substring(0, 8).ToUpper()
                    , logData.LogType.ToString());

                string fileFullName = filePath + fileName;

                XmlHelper.Serialize(fileFullName, logData);
            }
            catch
            {
                // do nothing.
            }
        }
    }
}
